import socket
import time
import struct
import threading
import datetime

myaddress = (socket.gethostbyname(socket.gethostname()), 49152)

xml = '''<?xml version="1.0"?>
<root xmlns="urn:schemas-upnp-org:device-1-0">
    <specVersion>
        <major>1</major>
        <minor>0</minor>
    </specVersion>
    <device>
        <deviceType>urn:schemas-upnp-org:device:InternetGatewayDevice:1</deviceType>
        <friendlyName>Linux Internet Gateway Device</friendlyName>
        <manufacturer>Linux UPnP IGD Project</manufacturer>
        <manufacturerURL>http://linux-igd.sourceforge.net</manufacturerURL>
        <modelName>IGD Version 1.00</modelName>
        <UDN>uuid:75802409-bccb-40e7-8e6c-fa095ecce13e</UDN>
        <iconList>
            <icon>
                <mimetype>image/gif</mimetype>
                <width>118</width>
                <height>119</height>
                <depth>8</depth>
                <url>/ligd.gif</url>
            </icon>
        </iconList>
        <serviceList>
               <service>
                   <serviceType>urn:schemas-dummy-com:service:Dummy:1</serviceType>
                   <serviceId>urn:dummy-com:serviceId:dummy1</serviceId>
                   <controlURL>/dummy</controlURL>
                   <eventSubURL>/dummy</eventSubURL>
                   <SCPDURL>/dummy.xml</SCPDURL>
                </service>
        </serviceList>
        <deviceList>
            <device>
                <deviceType>urn:schemas-upnp-org:device:WANDevice:1</deviceType>
                <friendlyName>WANDevice</friendlyName>
                <manufacturer>Linux UPnP IGD Project</manufacturer>
                <manufacturerURL>http://linux-igd.sourceforge.net</manufacturerURL>
                <modelDescription>WAN Device on Linux IGD</modelDescription>
                <modelName>Linux IGD</modelName>
                <modelNumber>1.00</modelNumber>
                <modelURL>http://linux-igd.sourceforge.net</modelURL>
                <serialNumber>1.00</serialNumber>
                <UDN>uuid:75802409-bccb-40e7-8e6c-fa095ecce13e</UDN>
                <UPC>Linux IGD</UPC>
                <serviceList>
                    <service>
                        <serviceType>urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1</serviceType>
                        <serviceId>urn:upnp-org:serviceId:WANCommonIFC1</serviceId>
                        <controlURL>/upnp/control/WANCommonIFC1</controlURL>
                        <eventSubURL>/upnp/control/WANCommonIFC1</eventSubURL>
                        <SCPDURL>/gateicfgSCPD.xml</SCPDURL>
                    </service>
                </serviceList>
                <deviceList>
                    <device>
                        <deviceType>urn:schemas-upnp-org:device:WANConnectionDevice:1</deviceType>
                        <friendlyName>WANConnectionDevice</friendlyName>
                        <manufacturer>Linux UPnP IGD Project</manufacturer>
                        <manufacturerURL>http://linux-igd.sourceforge.net</manufacturerURL>
                        <modelDescription>WanConnectionDevice on Linux IGD</modelDescription>
                        <modelName>Linux IGD</modelName>
                        <modelNumber>0.95</modelNumber>
                        <modelURL>http://linux-igd.sourceforge.net</modelURL>
                        <serialNumber>0.95</serialNumber>
                        <UDN>uuid:75802409-bccb-40e7-8e6c-fa095ecce13e</UDN>
                        <UPC>Linux IGD</UPC>
                        <serviceList>
                            <service>
                                <serviceType>urn:schemas-upnp-org:service:WANIPConnection:1</serviceType>
                                <serviceId>urn:upnp-org:serviceId:WANIPConn1</serviceId>
                                <controlURL>/upnp/control/WANIPConn1</controlURL>
                                <eventSubURL>/upnp/control/WANIPConn1</eventSubURL>
                                <SCPDURL>/gateconnSCPD.xml</SCPDURL>
                            </service>
                        </serviceList>
                    </device>
                </deviceList>
            </device>
        </deviceList>
    </device>
</root>

'''

xmlack = \
'''HTTP/1.1 200 OK\r
CONTENT-LENGTH: %d\r
CONTENT-TYPE: text/xml\r
DATE: %s\r
LAST-MODIFIED: %s\r
SERVER: Linux/3.5.0-23-generic, UPnP/1.0, Portable SDK for UPnP devices/1.6.6\r
X-User-Agent: redsonic\r
CONNECTION: close\r
\r
'''

fakeigd = \
'''HTTP/1.1 200 OK\r
DATE: %s\r
CACHE-CONTROL: max-age=1\r
EXT:\r
LOCATION: http://%s:%d/gatedesc.xml\r
SERVER: Linux/3.5.0-23-generic, UPnP/1.0, Portable SDK for UPnP devices/1.6.6\r
X-User-Agent: redsonic\r
ST: urn:schemas-upnp-org:device:InternetGatewayDevice:1\r
USN: uuid:75802409-bccb-40e7-8e6c-fa095ecce13e::urn:schemas-upnp-org:device:InternetGatewayDevice:1\r
\r
'''

def trigger(sock):
    try:
        data = sock.recv(65535)
        print data
        now = str(datetime.datetime.utcnow().strftime('%a, %d %b %Y %H:%M:%S GMT'))
        hoho = xmlack % (len(xml), now, now) + xml
        sock.send(hoho)
    except:
        pass
    pass


def webserver():
    r = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    r.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    r.bind(('0.0.0.0', myaddress[1]))
    r.listen(5)

    while True:
        client = r.accept()[0]
        trigger(client)
        client.shutdown(socket.SHUT_RDWR)
        client.close()
    pass

wwwthread = threading.Thread(target = webserver)
wwwthread.start()

s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 1)
s.bind(('0.0.0.0', 1900))

mreq = struct.pack('=4sl', socket.inet_aton('239.255.255.250'), socket.INADDR_ANY)
s.setsockopt(socket.SOL_IP, socket.IP_ADD_MEMBERSHIP, mreq)

while True:
    (ssdp, addr) = s.recvfrom(8192)

    if 'M-SEARCH' in ssdp and 'urn:schemas-upnp-org:device:InternetGatewayDevice:1' in ssdp:
        now = str(datetime.datetime.utcnow().strftime('%a, %d %b %Y %H:%M:%S GMT'))
        print ssdp
        q = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        q.sendto(fakeigd % (now, myaddress[0], myaddress[1]), addr)
        print fakeigd % (now, myaddress[0], myaddress[1])
        q.close()
        #break

print 'done'
